{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "5hIbr52I7Z7U"
   },
   "source": [
    "Deep Learning\n",
    "=============\n",
    "\n",
    "Assignment 1\n",
    "------------\n",
    "\n",
    "The objective of this assignment is to learn about simple data curation practices, and familiarize you with some of the data we'll be reusing later.\n",
    "\n",
    "This notebook uses the [notMNIST](http://yaroslavvb.blogspot.com/2011/09/notmnist-dataset.html) dataset to be used with python experiments. This dataset is designed to look like the classic [MNIST](http://yann.lecun.com/exdb/mnist/) dataset, while looking a little more like real data: it's a harder task, and the data is a lot less 'clean' than MNIST."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "apJbCsBHl-2A"
   },
   "outputs": [],
   "source": [
    "# These are all the modules we'll be using later. Make sure you can import them\n",
    "# before proceeding further.\n",
    "from __future__ import print_function\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import os\n",
    "import sys\n",
    "import tarfile\n",
    "from IPython.display import display, Image\n",
    "from scipy import ndimage\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from six.moves.urllib.request import urlretrieve\n",
    "from six.moves import cPickle as pickle"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "jNWGtZaXn-5j"
   },
   "source": [
    "First, we'll download the dataset to our local machine. The data consists of characters rendered in a variety of fonts on a 28x28 image. The labels are limited to 'A' through 'J' (10 classes). The training set has about 500k and the testset 19000 labelled examples. Given these sizes, it should be possible to train models quickly on any machine."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 186058,
     "status": "ok",
     "timestamp": 1444485672507,
     "user": {
      "color": "#1FA15D",
      "displayName": "Vincent Vanhoucke",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "05076109866853157986",
      "photoUrl": "//lh6.googleusercontent.com/-cCJa7dTDcgQ/AAAAAAAAAAI/AAAAAAAACgw/r2EZ_8oYer4/s50-c-k-no/photo.jpg",
      "sessionId": "2a0a5e044bb03b66",
      "userId": "102167687554210253930"
     },
     "user_tz": 420
    },
    "id": "EYRJ4ICW6-da",
    "outputId": "0d0f85df-155f-4a89-8e7e-ee32df36ec8d"
   },
   "outputs": [],
   "source": [
    "url = 'http://yaroslavvb.com/upload/notMNIST/'\n",
    "\n",
    "def maybe_download(filename, expected_bytes, force=False):\n",
    "  \"\"\"Download a file if not present, and make sure it's the right size.\"\"\"\n",
    "  if force or not os.path.exists(filename):\n",
    "    filename, _ = urlretrieve(url + filename, filename)\n",
    "  statinfo = os.stat(filename)\n",
    "  if statinfo.st_size == expected_bytes:\n",
    "    print('Found and verified', filename)\n",
    "  else:\n",
    "    raise Exception(\n",
    "      'Failed to verify ' + filename + '. Can you get to it with a browser?')\n",
    "  return filename\n",
    "\n",
    "# Could not get the download to work through python for some reason.\n",
    "# Completed it manually through the web browser.\n",
    "# train_filename = maybe_download('notMNIST_large.tar.gz', 247336696)\n",
    "# test_filename = maybe_download('notMNIST_small.tar.gz', 8458043)\n",
    "train_filename = 'notMNIST_large.tar.gz'\n",
    "test_filename = 'notMNIST_small.tar.gz'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "cC3p0oEyF8QT"
   },
   "source": [
    "Extract the dataset from the compressed .tar.gz file.\n",
    "This should give you a set of directories, labelled A through J."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 186055,
     "status": "ok",
     "timestamp": 1444485672525,
     "user": {
      "color": "#1FA15D",
      "displayName": "Vincent Vanhoucke",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "05076109866853157986",
      "photoUrl": "//lh6.googleusercontent.com/-cCJa7dTDcgQ/AAAAAAAAAAI/AAAAAAAACgw/r2EZ_8oYer4/s50-c-k-no/photo.jpg",
      "sessionId": "2a0a5e044bb03b66",
      "userId": "102167687554210253930"
     },
     "user_tz": 420
    },
    "id": "H8CBE-WZ8nmj",
    "outputId": "ef6c790c-2513-4b09-962e-27c79390c762"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "notMNIST_large already present - Skipping extraction of notMNIST_large.tar.gz.\n",
      "['notMNIST_large/A', 'notMNIST_large/B', 'notMNIST_large/C', 'notMNIST_large/D', 'notMNIST_large/E', 'notMNIST_large/F', 'notMNIST_large/G', 'notMNIST_large/H', 'notMNIST_large/I', 'notMNIST_large/J']\n",
      "notMNIST_small already present - Skipping extraction of notMNIST_small.tar.gz.\n",
      "['notMNIST_small/A', 'notMNIST_small/B', 'notMNIST_small/C', 'notMNIST_small/D', 'notMNIST_small/E', 'notMNIST_small/F', 'notMNIST_small/G', 'notMNIST_small/H', 'notMNIST_small/I', 'notMNIST_small/J']\n"
     ]
    }
   ],
   "source": [
    "num_classes = 10\n",
    "np.random.seed(133)\n",
    "\n",
    "def maybe_extract(filename, force=False):\n",
    "  root = os.path.splitext(os.path.splitext(filename)[0])[0]  # remove .tar.gz\n",
    "  if os.path.isdir(root) and not force:\n",
    "    # You may override by setting force=True.\n",
    "    print('%s already present - Skipping extraction of %s.' % (root, filename))\n",
    "  else:\n",
    "    print('Extracting data for %s. This may take a while. Please wait.' % root)\n",
    "    tar = tarfile.open(filename)\n",
    "    sys.stdout.flush()\n",
    "    tar.extractall()\n",
    "    tar.close()\n",
    "  data_folders = [\n",
    "    os.path.join(root, d) for d in sorted(os.listdir(root))\n",
    "    if os.path.isdir(os.path.join(root, d))]\n",
    "  if len(data_folders) != num_classes:\n",
    "    raise Exception(\n",
    "      'Expected %d folders, one per class. Found %d instead.' % (\n",
    "        num_classes, len(data_folders)))\n",
    "  print(data_folders)\n",
    "  return data_folders\n",
    "  \n",
    "train_folders = maybe_extract(train_filename)\n",
    "test_folders = maybe_extract(test_filename)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "4riXK3IoHgx6"
   },
   "source": [
    "---\n",
    "Problem 1\n",
    "---------\n",
    "\n",
    "Let's take a peek at some of the data to make sure it looks sensible. Each exemplar should be an image of a character A through J rendered in a different font. Display a sample of the images that we just downloaded. Hint: you can use the package IPython.display."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAACRUlEQVR4nG2STUiUYRDH//O8z368\nvvu9qGyZH7upaaYb9GEYlVFRknTJsFsWHTt1rEvnunSIQKhDF6EuBR6MwkzE0CQJKiFF11owd9Vd\nM0133/eZDtruYs1pmP/8/swwA+TCZRB0GyhfKUi9zpbwSNn7KWJsD4Ezj4d4+tvtCvEfreH+GGcs\njt/Nu+XbxO9qlmB/Sd0/qA0XlVLMnJ6/k5tkq0tkz3fNKwLYa2gV22wJh9itWRYYc5fLcsiW6HLW\nGUzmIni35yC4UCQzsj+saO3N+DipYNVplV+f4K58Ns4WD/uv9/1kjt2r3YQ2yeLETNQkNbA8s6wB\npd7yvC1rqQtXVyRNJAID/SMxOE85vIpypLzkM3hpcHhBvf5RzDBaG3IkWc3NmkBqJQ271S9ZFe+I\nh7S/trvML0BqcvirWF9K9whYnS1rNgASIOG5doRJD54ITB2eMU4u+bTMlbFpABLE/r1NToKokY3R\nwY6AYSfQgcjiIjGgaU3dSVaKmVmtWhvMzCY/DUtAgOjY2Q0wccYC67BDKQD1uhMQZLoDJT4I0yRO\nILH6fZ0FC+j1RSDJjrZmMjj7cK79ecyfOqr37uuotVxVNz4kCLL+5ifO8pNzERR54LOHg/Zbr2bZ\n+tgDErqjuoZlKrYQx/qKXM5OpzIPRn0QO5NdmnA3ttpUenB2coMUm8zEWvrlrwX2tFWawt8ZRppG\ne9XWhZkVJoYcq7aIuUfi7bvS4y8eJQu/zdeth/qin+OQoUqbSycqFPWgLDec7e4/wqfzL3yRo74A\nAAAASUVORK5CYII=\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from IPython.display import Image\n",
    "Image(os.getcwd() + '/notMNIST_small/A/MDEtMDEtMDAudHRm.png')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "PBdkjESPK8tw"
   },
   "source": [
    "Now let's load the data in a more manageable format. Since, depending on your computer setup you might not be able to fit it all in memory, we'll load each class into a separate dataset, store them on disk and curate them independently. Later we'll merge them into a single dataset of manageable size.\n",
    "\n",
    "We'll convert the entire dataset into a 3D array (image index, x, y) of floating point values, normalized to have approximately zero mean and standard deviation ~0.5 to make training easier down the road. \n",
    "\n",
    "A few images might not be readable, we'll just skip them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 30
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 399874,
     "status": "ok",
     "timestamp": 1444485886378,
     "user": {
      "color": "#1FA15D",
      "displayName": "Vincent Vanhoucke",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "05076109866853157986",
      "photoUrl": "//lh6.googleusercontent.com/-cCJa7dTDcgQ/AAAAAAAAAAI/AAAAAAAACgw/r2EZ_8oYer4/s50-c-k-no/photo.jpg",
      "sessionId": "2a0a5e044bb03b66",
      "userId": "102167687554210253930"
     },
     "user_tz": 420
    },
    "id": "h7q0XhG3MJdf",
    "outputId": "92c391bb-86ff-431d-9ada-315568a19e59",
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "notMNIST_large/A.pickle already present - Skipping pickling.\n",
      "notMNIST_large/B.pickle already present - Skipping pickling.\n",
      "notMNIST_large/C.pickle already present - Skipping pickling.\n",
      "notMNIST_large/D.pickle already present - Skipping pickling.\n",
      "notMNIST_large/E.pickle already present - Skipping pickling.\n",
      "notMNIST_large/F.pickle already present - Skipping pickling.\n",
      "notMNIST_large/G.pickle already present - Skipping pickling.\n",
      "notMNIST_large/H.pickle already present - Skipping pickling.\n",
      "notMNIST_large/I.pickle already present - Skipping pickling.\n",
      "notMNIST_large/J.pickle already present - Skipping pickling.\n",
      "notMNIST_small/A.pickle already present - Skipping pickling.\n",
      "notMNIST_small/B.pickle already present - Skipping pickling.\n",
      "notMNIST_small/C.pickle already present - Skipping pickling.\n",
      "notMNIST_small/D.pickle already present - Skipping pickling.\n",
      "notMNIST_small/E.pickle already present - Skipping pickling.\n",
      "notMNIST_small/F.pickle already present - Skipping pickling.\n",
      "notMNIST_small/G.pickle already present - Skipping pickling.\n",
      "notMNIST_small/H.pickle already present - Skipping pickling.\n",
      "notMNIST_small/I.pickle already present - Skipping pickling.\n",
      "notMNIST_small/J.pickle already present - Skipping pickling.\n"
     ]
    }
   ],
   "source": [
    "image_size = 28  # Pixel width and height.\n",
    "pixel_depth = 255.0  # Number of levels per pixel.\n",
    "\n",
    "def load_letter(folder, min_num_images):\n",
    "  \"\"\"Load the data for a single letter label.\"\"\"\n",
    "  image_files = os.listdir(folder)\n",
    "  dataset = np.ndarray(shape=(len(image_files), image_size, image_size),\n",
    "                         dtype=np.float32)\n",
    "  image_index = 0\n",
    "  print(folder)\n",
    "  for image in os.listdir(folder):\n",
    "    image_file = os.path.join(folder, image)\n",
    "    try:\n",
    "      image_data = (ndimage.imread(image_file).astype(float) - \n",
    "                    pixel_depth / 2) / pixel_depth\n",
    "      if image_data.shape != (image_size, image_size):\n",
    "        raise Exception('Unexpected image shape: %s' % str(image_data.shape))\n",
    "      dataset[image_index, :, :] = image_data\n",
    "      image_index += 1\n",
    "    except IOError as e:\n",
    "      print('Could not read file - it\\'s ok, skipping.')\n",
    "    \n",
    "  num_images = image_index\n",
    "  dataset = dataset[0:num_images, :, :]\n",
    "  if num_images < min_num_images:\n",
    "    raise Exception('Many fewer images than expected: %d < %d' %\n",
    "                    (num_images, min_num_images))\n",
    "    \n",
    "  print('Full dataset tensor:', dataset.shape)\n",
    "  print('Mean:', np.mean(dataset))\n",
    "  print('Standard deviation:', np.std(dataset))\n",
    "  return dataset\n",
    "        \n",
    "def maybe_pickle(data_folders, min_num_images_per_class, force=False):\n",
    "  dataset_names = []\n",
    "  for folder in data_folders:\n",
    "    set_filename = folder + '.pickle'\n",
    "    dataset_names.append(set_filename)\n",
    "    if os.path.exists(set_filename) and not force:\n",
    "      # You may override by setting force=True.\n",
    "      print('%s already present - Skipping pickling.' % set_filename)\n",
    "    else:\n",
    "      print('Pickling %s.' % set_filename)\n",
    "      dataset = load_letter(folder, min_num_images_per_class)\n",
    "      try:\n",
    "        with open(set_filename, 'wb') as f:\n",
    "          pickle.dump(dataset, f, pickle.HIGHEST_PROTOCOL)\n",
    "      except Exception as e:\n",
    "        print('Unable to save data to', set_filename, ':', e)\n",
    "  \n",
    "  return dataset_names\n",
    "\n",
    "train_datasets = maybe_pickle(train_folders, 45000)\n",
    "test_datasets = maybe_pickle(test_folders, 1800)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "vUdbskYE2d87"
   },
   "source": [
    "---\n",
    "Problem 2\n",
    "---------\n",
    "\n",
    "Let's verify that the data still looks good. Displaying a sample of the labels and images from the ndarray. Hint: you can use matplotlib.pyplot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['notMNIST_large/A.pickle',\n",
       " 'notMNIST_large/B.pickle',\n",
       " 'notMNIST_large/C.pickle',\n",
       " 'notMNIST_large/D.pickle',\n",
       " 'notMNIST_large/E.pickle',\n",
       " 'notMNIST_large/F.pickle',\n",
       " 'notMNIST_large/G.pickle',\n",
       " 'notMNIST_large/H.pickle',\n",
       " 'notMNIST_large/I.pickle',\n",
       " 'notMNIST_large/J.pickle']"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_datasets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(52909, 28, 28)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "file = open(train_datasets[0], 'rb')\n",
    "train_A = pickle.load(file)\n",
    "train_A.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f0771677bd0>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f0773728990>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "plt.imshow(train_A[0,:,:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "cYznx5jUwzoO"
   },
   "source": [
    "---\n",
    "Problem 3\n",
    "---------\n",
    "Another check: we expect the data to be balanced across classes. Verify that."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Checking number of images per class...\n",
      "notMNIST_large/A.pickle size: 52909\n",
      "notMNIST_large/B.pickle size: 52911\n",
      "notMNIST_large/C.pickle size: 52912\n",
      "notMNIST_large/D.pickle size: 52911\n",
      "notMNIST_large/E.pickle size: 52912\n",
      "notMNIST_large/F.pickle size: 52912\n",
      "notMNIST_large/G.pickle size: 52912\n",
      "notMNIST_large/H.pickle size: 52912\n",
      "notMNIST_large/I.pickle size: 52912\n",
      "notMNIST_large/J.pickle size: 52911\n",
      "notMNIST_small/A.pickle size: 1872\n",
      "notMNIST_small/B.pickle size: 1873\n",
      "notMNIST_small/C.pickle size: 1873\n",
      "notMNIST_small/D.pickle size: 1873\n",
      "notMNIST_small/E.pickle size: 1873\n",
      "notMNIST_small/F.pickle size: 1872\n",
      "notMNIST_small/G.pickle size: 1872\n",
      "notMNIST_small/H.pickle size: 1872\n",
      "notMNIST_small/I.pickle size: 1872\n",
      "notMNIST_small/J.pickle size: 1872\n"
     ]
    }
   ],
   "source": [
    "print('Checking number of images per class...')\n",
    "for letter in train_datasets:\n",
    "    file = open(letter, 'rb')\n",
    "    dataset = pickle.load(file)\n",
    "    print(letter + ' size: ' + str(dataset.shape[0]))\n",
    "for letter in test_datasets:\n",
    "    file = open(letter, 'rb')\n",
    "    dataset = pickle.load(file)\n",
    "    print(letter + ' size: ' + str(dataset.shape[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "LA7M7K22ynCt"
   },
   "source": [
    "Merge and prune the training data as needed. Depending on your computer setup, you might not be able to fit it all in memory, and you can tune `train_size` as needed. The labels will be stored into a separate array of integers 0 through 9.\n",
    "\n",
    "Also create a validation dataset for hyperparameter tuning."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 411281,
     "status": "ok",
     "timestamp": 1444485897869,
     "user": {
      "color": "#1FA15D",
      "displayName": "Vincent Vanhoucke",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "05076109866853157986",
      "photoUrl": "//lh6.googleusercontent.com/-cCJa7dTDcgQ/AAAAAAAAAAI/AAAAAAAACgw/r2EZ_8oYer4/s50-c-k-no/photo.jpg",
      "sessionId": "2a0a5e044bb03b66",
      "userId": "102167687554210253930"
     },
     "user_tz": 420
    },
    "id": "s3mWgZLpyuzq",
    "outputId": "8af66da6-902d-4719-bedc-7c9fb7ae7948"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training: (200000, 28, 28) (200000,)\n",
      "Validation: (10000, 28, 28) (10000,)\n",
      "Testing: (10000, 28, 28) (10000,)\n"
     ]
    }
   ],
   "source": [
    "def make_arrays(nb_rows, img_size):\n",
    "  if nb_rows:\n",
    "    dataset = np.ndarray((nb_rows, img_size, img_size), dtype=np.float32)\n",
    "    labels = np.ndarray(nb_rows, dtype=np.int32)\n",
    "  else:\n",
    "    dataset, labels = None, None\n",
    "  return dataset, labels\n",
    "\n",
    "def merge_datasets(pickle_files, train_size, valid_size=0):\n",
    "  num_classes = len(pickle_files)\n",
    "  valid_dataset, valid_labels = make_arrays(valid_size, image_size)\n",
    "  train_dataset, train_labels = make_arrays(train_size, image_size)\n",
    "  vsize_per_class = valid_size // num_classes\n",
    "  tsize_per_class = train_size // num_classes\n",
    "    \n",
    "  start_v, start_t = 0, 0\n",
    "  end_v, end_t = vsize_per_class, tsize_per_class\n",
    "  end_l = vsize_per_class+tsize_per_class\n",
    "  for label, pickle_file in enumerate(pickle_files):       \n",
    "    try:\n",
    "      with open(pickle_file, 'rb') as f:\n",
    "        letter_set = pickle.load(f)\n",
    "        # let's shuffle the letters to have random validation and training set\n",
    "        np.random.shuffle(letter_set)\n",
    "        if valid_dataset is not None:\n",
    "          valid_letter = letter_set[:vsize_per_class, :, :]\n",
    "          valid_dataset[start_v:end_v, :, :] = valid_letter\n",
    "          valid_labels[start_v:end_v] = label\n",
    "          start_v += vsize_per_class\n",
    "          end_v += vsize_per_class\n",
    "                    \n",
    "        train_letter = letter_set[vsize_per_class:end_l, :, :]\n",
    "        train_dataset[start_t:end_t, :, :] = train_letter\n",
    "        train_labels[start_t:end_t] = label\n",
    "        start_t += tsize_per_class\n",
    "        end_t += tsize_per_class\n",
    "    except Exception as e:\n",
    "      print('Unable to process data from', pickle_file, ':', e)\n",
    "      raise\n",
    "    \n",
    "  return valid_dataset, valid_labels, train_dataset, train_labels\n",
    "            \n",
    "            \n",
    "train_size = 200000\n",
    "valid_size = 10000\n",
    "test_size = 10000\n",
    "\n",
    "valid_dataset, valid_labels, train_dataset, train_labels = merge_datasets(\n",
    "  train_datasets, train_size, valid_size)\n",
    "_, _, test_dataset, test_labels = merge_datasets(test_datasets, test_size)\n",
    "\n",
    "print('Training:', train_dataset.shape, train_labels.shape)\n",
    "print('Validation:', valid_dataset.shape, valid_labels.shape)\n",
    "print('Testing:', test_dataset.shape, test_labels.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "GPTCnjIcyuKN"
   },
   "source": [
    "Next, we'll randomize the data. It's important to have the labels well shuffled for the training and test distributions to match."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "6WZ2l2tN2zOL"
   },
   "outputs": [],
   "source": [
    "def randomize(dataset, labels):\n",
    "  permutation = np.random.permutation(labels.shape[0])\n",
    "  shuffled_dataset = dataset[permutation,:,:]\n",
    "  shuffled_labels = labels[permutation]\n",
    "  return shuffled_dataset, shuffled_labels\n",
    "train_dataset, train_labels = randomize(train_dataset, train_labels)\n",
    "test_dataset, test_labels = randomize(test_dataset, test_labels)\n",
    "valid_dataset, valid_labels = randomize(valid_dataset, valid_labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "puDUTe6t6USl"
   },
   "source": [
    "---\n",
    "Problem 4\n",
    "---------\n",
    "Convince yourself that the data is still good after shuffling!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f0773713790>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, ax = plt.subplots(3, 1)\n",
    "ax[0].hist(train_labels, 10)\n",
    "ax[1].hist(test_labels, 10)\n",
    "ax[2].hist(valid_labels, 10)\n",
    "fig.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "tIQJaJuwg5Hw"
   },
   "source": [
    "Finally, let's save the data for later reuse:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     }
    },
    "colab_type": "code",
    "collapsed": true,
    "id": "QiR_rETzem6C"
   },
   "outputs": [],
   "source": [
    "pickle_file = 'notMNIST.pickle'\n",
    "\n",
    "try:\n",
    "  f = open(pickle_file, 'wb')\n",
    "  save = {\n",
    "    'train_dataset': train_dataset,\n",
    "    'train_labels': train_labels,\n",
    "    'valid_dataset': valid_dataset,\n",
    "    'valid_labels': valid_labels,\n",
    "    'test_dataset': test_dataset,\n",
    "    'test_labels': test_labels,\n",
    "    }\n",
    "  pickle.dump(save, f, pickle.HIGHEST_PROTOCOL)\n",
    "  f.close()\n",
    "except Exception as e:\n",
    "  print('Unable to save data to', pickle_file, ':', e)\n",
    "  raise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "cellView": "both",
    "colab": {
     "autoexec": {
      "startup": false,
      "wait_interval": 0
     },
     "output_extras": [
      {
       "item_id": 1
      }
     ]
    },
    "colab_type": "code",
    "collapsed": false,
    "executionInfo": {
     "elapsed": 413065,
     "status": "ok",
     "timestamp": 1444485899688,
     "user": {
      "color": "#1FA15D",
      "displayName": "Vincent Vanhoucke",
      "isAnonymous": false,
      "isMe": true,
      "permissionId": "05076109866853157986",
      "photoUrl": "//lh6.googleusercontent.com/-cCJa7dTDcgQ/AAAAAAAAAAI/AAAAAAAACgw/r2EZ_8oYer4/s50-c-k-no/photo.jpg",
      "sessionId": "2a0a5e044bb03b66",
      "userId": "102167687554210253930"
     },
     "user_tz": 420
    },
    "id": "hQbLjrW_iT39",
    "outputId": "b440efc6-5ee1-4cbc-d02d-93db44ebd956"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Compressed pickle size: 690800441\n"
     ]
    }
   ],
   "source": [
    "statinfo = os.stat(pickle_file)\n",
    "print('Compressed pickle size:', statinfo.st_size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "gE_cRAQB33lk"
   },
   "source": [
    "---\n",
    "Problem 5\n",
    "---------\n",
    "\n",
    "By construction, this dataset might contain a lot of overlapping samples, including training data that's also contained in the validation and test set! Overlap between training and test can skew the results if you expect to use your model in an environment where there is never an overlap, but are actually ok if you expect to see training samples recur when you use it.\n",
    "Measure how much overlap there is between training, validation and test samples.\n",
    "\n",
    "Optional questions:\n",
    "- What about near duplicates between datasets? (images that are almost identical)\n",
    "- Create a sanitized validation and test set, and compare your accuracy on those in subsequent assignments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Duplicates inside training set:  12707\n",
      "Duplicates between training and validation:  942\n",
      "Duplicates between training and test:  1133\n"
     ]
    }
   ],
   "source": [
    "train_dataset.flags.writeable = False\n",
    "valid_dataset.flags.writeable = False\n",
    "test_dataset.flags.writeable = False\n",
    "\n",
    "train_hash = [hash(e.tobytes()) for e in train_dataset]\n",
    "valid_hash = [hash(e.tobytes()) for e in valid_dataset]\n",
    "test_hash = [hash(e.tobytes()) for e in test_dataset]\n",
    "\n",
    "unique_train_hash = set(train_hash)\n",
    "valid_overlap = unique_train_hash.intersection(set(valid_hash))\n",
    "test_overlap = unique_train_hash.intersection(set(test_hash))\n",
    "\n",
    "print('Duplicates inside training set: ', len(train_hash) - len(unique_train_hash))\n",
    "print('Duplicates between training and validation: ', len(valid_overlap))\n",
    "print('Duplicates between training and test: ', len(test_overlap))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "L8oww1s4JMQx"
   },
   "source": [
    "---\n",
    "Problem 6\n",
    "---------\n",
    "\n",
    "Let's get an idea of what an off-the-shelf classifier can give you on this data. It's always good to check that there is something to learn, and that it's a problem that is not so trivial that a canned solution solves it.\n",
    "\n",
    "Train a simple model on this data using 50, 100, 1000 and 5000 training samples. Hint: you can use the LogisticRegression model from sklearn.linear_model.\n",
    "\n",
    "Optional question: train an off-the-shelf model on all the data!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training score =  0.9392\n",
      "Test score =  0.8478\n"
     ]
    }
   ],
   "source": [
    "from sklearn.linear_model import LogisticRegression\n",
    "\n",
    "train_sample = train_dataset[:5000,:,:]\n",
    "train_sample_labels = train_labels[:5000]\n",
    "\n",
    "(samples, width, height) = train_sample.shape\n",
    "train_sample = np.reshape(train_sample, (samples, width * height))\n",
    "\n",
    "(samples, width, height) = test_dataset.shape\n",
    "test_dataset_reshaped = np.reshape(test_dataset, (samples, width * height))\n",
    "\n",
    "model = LogisticRegression(penalty='l2', C=1.0)\n",
    "model.fit(train_sample, train_sample_labels)\n",
    "\n",
    "train_score = model.score(train_sample, train_sample_labels)\n",
    "test_score = model.score(test_dataset_reshaped, test_labels)\n",
    "print('Training score = ', train_score)\n",
    "print('Test score = ', test_score)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "default_view": {},
   "name": "1_notmnist.ipynb",
   "provenance": [],
   "version": "0.3.2",
   "views": {}
  },
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
